package com.example.demo.common.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.common.entity.Prediction1;
import com.example.demo.common.entity.Prediction2;
import com.example.demo.common.entity.Prediction3;
import com.example.demo.common.mapper.Prediction1Mapper;
import com.example.demo.common.mapper.Prediction2Mapper;
import com.example.demo.common.mapper.Prediction3Mapper;
import com.example.demo.common.service.Prediction1Service;
import com.example.demo.common.service.Prediction2Service;
import com.example.demo.common.service.Prediction3Service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/prediction")
public class PredictionController {

    @Resource private Prediction1Mapper prediction1Mapper;
    @Resource private Prediction2Mapper prediction2Mapper;
    @Resource private Prediction3Mapper prediction3Mapper;
    @Resource private Prediction1Service prediction1Service;
    @Resource private Prediction2Service prediction2Service;
    @Resource private Prediction3Service prediction3Service;

    private final String flaskBaseUrl = "http://localhost:5000/predict";

    private final ObjectMapper objectMapper = new ObjectMapper();

    // 创建配置好的RestTemplate
    private RestTemplate createRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();

        // 添加UTF-8编码的StringHttpMessageConverter
        StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
        stringConverter.setWriteAcceptCharset(false);

        // 配置JSON转换器
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        jsonConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));

        restTemplate.getMessageConverters().add(0, stringConverter);
        restTemplate.getMessageConverters().add(1, jsonConverter);

        return restTemplate;
    }

    // ============= Prediction1 操作 =============

    @PostMapping("/prediction1")
    public Result<?> savePrediction1(@RequestBody Prediction1 prediction1) {
        Date date = new Date();
        prediction1.setPredictTime(date);

        // 请求 Flask 预测屈服与抗拉
        RestTemplate restTemplate = createRestTemplate();
        String url = flaskBaseUrl + "/prediction1";

        try {
            // 创建只包含模型需要的字段的Map
            Map<String, Object> requestData = createPrediction1RequestData(prediction1);

            // 打印发送给Flask的数据，用于调试
            System.out.println("Sending to Flask prediction1: " + objectMapper.writeValueAsString(requestData));

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestData, headers);

            ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);

            // 打印Flask返回的响应，用于调试
            System.out.println("Flask response: " + response.getBody());

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                JsonNode json = objectMapper.readTree(response.getBody());
                if (json.has("yield_strength") && json.has("tensile_strength")) {
                    prediction1.setQf((float) json.get("yield_strength").asDouble());
                    prediction1.setKl((float) json.get("tensile_strength").asDouble());
                } else {
                    System.err.println("Flask response missing expected fields: " + response.getBody());
                    return Result.error("预测响应格式错误", response.getBody()); // 修改为两个参数
                }
            } else {
                System.err.println("Flask response error: " + response.getStatusCode());
                return Result.error("预测服务返回错误", response.getStatusCode().toString()); // 修改为两个参数
            }
        } catch (Exception e) {
            e.printStackTrace(); // 打印完整堆栈信息
            return Result.error("预测失败", e.getMessage()); // 修改为两个参数
        }

        prediction1Service.savePrediction1(prediction1);
        return Result.success();
    }

    // 创建适合Flask模型的请求数据
    private Map<String, Object> createPrediction1RequestData(Prediction1 prediction1) {
        Map<String, Object> data = new HashMap<>();

        // 根据模型所需字段添加属性
        // 以下是示例，请根据实际Prediction1对象和Flask模型所需调整
        if (prediction1.getC() != null) data.put("C", prediction1.getC());
        if (prediction1.getMn() != null) data.put("Mn", prediction1.getMn());
        if (prediction1.getSi() != null) data.put("Si", prediction1.getSi());
        if (prediction1.getCr() != null) data.put("Cr", prediction1.getCr());
        if (prediction1.getAl() != null) data.put("Al", prediction1.getAl());
        if (prediction1.getNi() != null) data.put("Ni", prediction1.getNi());
        if (prediction1.getMo() != null) data.put("Mo", prediction1.getMo());
        if (prediction1.getV() != null) data.put("V", prediction1.getV());
        if (prediction1.getNb() != null) data.put("Nb", prediction1.getNb());
        if (prediction1.getB() != null) data.put("B", prediction1.getB());
        if (prediction1.getRa() != null) data.put("Ra", prediction1.getRa());
        if (prediction1.getPagb() != null) data.put("pagb", prediction1.getPagb());
        if (prediction1.getHapacket() != null) data.put("hapacket", prediction1.getHapacket());
        if (prediction1.getLapacket() != null) data.put("lapacket", prediction1.getLapacket());
        if (prediction1.getBlock() != null) data.put("block", prediction1.getBlock());
        if (prediction1.getSubblock() != null) data.put("subblock", prediction1.getSubblock());
        // 添加其他Flask模型需要的字段...

        return data;
    }

    @PutMapping("/prediction1")
    public Result<?> updatePrediction1(@RequestBody Prediction1 prediction1) {
        prediction1Service.updatePrediction1(prediction1);
        return Result.success();
    }

    @DeleteMapping("/prediction1/{id}")
    public Result<?> deletePrediction1(@PathVariable Long id) {
        prediction1Service.deleteById(id);
        return Result.success();
    }

    @GetMapping("/prediction1")
    public Result<?> findPrediction1Page(@RequestParam(defaultValue = "1") Integer pageNum,
                                         @RequestParam(defaultValue = "10") Integer pageSize,
                                         @RequestParam(defaultValue = "") String search) {
        LambdaQueryWrapper<Prediction1> wrapper = Wrappers.<Prediction1>lambdaQuery();
        if (StrUtil.isNotBlank(search)) {
            wrapper.like(Prediction1::getId, search);
        }
        Page<Prediction1> predictionPage = prediction1Mapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
        return Result.success(predictionPage);
    }

    // ============= Prediction2 操作 =============

    @PostMapping("/prediction2")
    public Result<?> savePrediction2(@RequestBody Prediction2 prediction2) {
        prediction2.setPredictTime(new Date());

        // 请求 Flask 预测冲击值
        RestTemplate restTemplate = createRestTemplate();
        String url = flaskBaseUrl + "/prediction2";

        try {
            // 创建只包含模型需要的字段的Map
            Map<String, Object> requestData = createPrediction2RequestData(prediction2);

            // 打印发送给Flask的数据，用于调试
            System.out.println("Sending to Flask prediction2: " + objectMapper.writeValueAsString(requestData));

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestData, headers);

            ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);

            // 打印Flask返回的响应，用于调试
            System.out.println("Flask response: " + response.getBody());

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                JsonNode json = objectMapper.readTree(response.getBody());
                if (json.has("impact_energy")) {
                    prediction2.setCjg((float) json.get("impact_energy").asDouble());
                } else {
                    System.err.println("Flask response missing expected fields: " + response.getBody());
                    return Result.error("预测响应格式错误", response.getBody()); // 修改为两个参数
                }
            } else {
                System.err.println("Flask response error: " + response.getStatusCode());
                return Result.error("预测服务返回错误", response.getStatusCode().toString()); // 修改为两个参数
            }
        } catch (Exception e) {
            e.printStackTrace(); // 打印完整堆栈信息
            return Result.error("预测失败", e.getMessage()); // 修改为两个参数
        }

        prediction2Service.savePrediction2(prediction2);
        return Result.success();
    }

    // 创建适合Flask模型的请求数据
    private Map<String, Object> createPrediction2RequestData(Prediction2 prediction2) {
        Map<String, Object> data = new HashMap<>();

        // 根据模型所需字段添加属性
        // 以下是示例，请根据实际Prediction2对象和Flask模型所需调整
        if (prediction2.getC() != null) data.put("C", prediction2.getC());
        if (prediction2.getMn() != null) data.put("Mn", prediction2.getMn());
        if (prediction2.getSi() != null) data.put("Si", prediction2.getSi());
        if (prediction2.getCr() != null) data.put("Cr", prediction2.getCr());
        if (prediction2.getAl() != null) data.put("Al", prediction2.getAl());
        if (prediction2.getNi() != null) data.put("Ni", prediction2.getNi());
        if (prediction2.getMo() != null) data.put("Mo", prediction2.getMo());
        if (prediction2.getV() != null) data.put("V", prediction2.getV());
        if (prediction2.getNb() != null) data.put("Nb", prediction2.getNb());
        if (prediction2.getB() != null) data.put("B", prediction2.getB());
        if (prediction2.getRa() != null) data.put("Ra", prediction2.getRa());
        if (prediction2.getPagb() != null) data.put("pagb", prediction2.getPagb());
        if (prediction2.getHapacket() != null) data.put("hapacket", prediction2.getHapacket());
        if (prediction2.getLapacket() != null) data.put("lapacket", prediction2.getLapacket());
        if (prediction2.getBlock() != null) data.put("block", prediction2.getBlock());
        if (prediction2.getSubblock() != null) data.put("subblock", prediction2.getSubblock());
        // 添加其他Flask模型需要的字段...

        return data;
    }

    @PutMapping("/prediction2")
    public Result<?> updatePrediction2(@RequestBody Prediction2 prediction2) {
        prediction2Service.updatePrediction2(prediction2);
        return Result.success();
    }

    @DeleteMapping("/prediction2/{id}")
    public Result<?> deletePrediction2(@PathVariable Long id) {
        prediction2Service.deleteById(id);
        return Result.success();
    }

    @GetMapping("/prediction2")
    public Result<?> findPrediction2Page(@RequestParam(defaultValue = "1") Integer pageNum,
                                         @RequestParam(defaultValue = "10") Integer pageSize,
                                         @RequestParam(defaultValue = "") String search) {
        LambdaQueryWrapper<Prediction2> wrapper = Wrappers.<Prediction2>lambdaQuery();
        if (StrUtil.isNotBlank(search)) {
            wrapper.like(Prediction2::getId, search);
        }
        Page<Prediction2> predictionPage = prediction2Mapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
        return Result.success(predictionPage);
    }

    // ============= Prediction3 操作 =============

    @PostMapping("/prediction3")
    public Result<?> savePrediction3(@RequestBody Prediction3 prediction3) {
        prediction3.setPredictTime(new Date());

        // 检查Flask服务是否有prediction3端点
        RestTemplate restTemplate = createRestTemplate();
        String url = flaskBaseUrl + "/prediction3";

        try {
            // 创建只包含模型需要的字段的Map
            Map<String, Object> requestData = createPrediction3RequestData(prediction3);

            // 打印发送给Flask的数据，用于调试
            System.out.println("Sending to Flask prediction3: " + objectMapper.writeValueAsString(requestData));

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestData, headers);

            // 发送请求前检查Flask端点是否可用
            try {
                ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);

                // 打印Flask返回的响应，用于调试
                System.out.println("Flask response: " + response.getBody());

                if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                    JsonNode json = objectMapper.readTree(response.getBody());
                    if (json.has("fatigue_strength")) {
                        prediction3.setPl((float) json.get("fatigue_strength").asDouble());
                    } else {
                        System.err.println("Flask response missing expected fields: " + response.getBody());
                        return Result.error("预测响应格式错误", response.getBody()); // 修改为两个参数
                    }
                } else {
                    System.err.println("Flask response error: " + response.getStatusCode());
                    return Result.error("预测服务返回错误", response.getStatusCode().toString()); // 修改为两个参数
                }
            } catch (Exception e) {
                System.err.println("Flask endpoint /prediction3 not available or error: " + e.getMessage());
                // 如果Flask端点不可用，设置一个默认值或者跳过预测
                // prediction3.setPl(0.0f); // 设置默认值
                return Result.error("疲劳强度预测服务不可用", e.getMessage()); // 修改为两个参数
            }
        } catch (Exception e) {
            e.printStackTrace(); // 打印完整堆栈信息
            return Result.error("预测失败", e.getMessage()); // 修改为两个参数
        }

        prediction3Service.savePrediction3(prediction3);
        return Result.success();
    }

    // 创建适合Flask模型的请求数据
    private Map<String, Object> createPrediction3RequestData(Prediction3 prediction3) {
        Map<String, Object> data = new HashMap<>();

        // 根据模型所需字段添加属性
        // 以下是示例，请根据实际Prediction3对象和Flask模型所需调整
        if (prediction3.getC() != null) data.put("C", prediction3.getC());
        if (prediction3.getMn() != null) data.put("Mn", prediction3.getMn());
        if (prediction3.getSi() != null) data.put("Si", prediction3.getSi());
        if (prediction3.getCr() != null) data.put("Cr", prediction3.getCr());
        if (prediction3.getAl() != null) data.put("Al", prediction3.getAl());
        if (prediction3.getNi() != null) data.put("Ni", prediction3.getNi());
        if (prediction3.getMo() != null) data.put("Mo", prediction3.getMo());
        if (prediction3.getV() != null) data.put("V", prediction3.getV());
        if (prediction3.getNb() != null) data.put("Nb", prediction3.getNb());
        if (prediction3.getB() != null) data.put("B", prediction3.getB());
        if (prediction3.getRa() != null) data.put("Ra", prediction3.getRa());
        if (prediction3.getPagb() != null) data.put("pagb", prediction3.getPagb());
        if (prediction3.getHapacket() != null) data.put("hapacket", prediction3.getHapacket());
        if (prediction3.getLapacket() != null) data.put("lapacket", prediction3.getLapacket());
        if (prediction3.getBlock() != null) data.put("block", prediction3.getBlock());
        if (prediction3.getSubblock() != null) data.put("subblock", prediction3.getSubblock());

        // 添加其他Flask模型需要的字段...

        return data;
    }

    @PutMapping("/prediction3")
    public Result<?> updatePrediction3(@RequestBody Prediction3 prediction3) {
        prediction3Service.updatePrediction3(prediction3);
        return Result.success();
    }

    @DeleteMapping("/prediction3/{id}")
    public Result<?> deletePrediction3(@PathVariable Long id) {
        prediction3Service.deleteById(id);
        return Result.success();
    }

    @GetMapping("/prediction3")
    public Result<?> findPrediction3Page(@RequestParam(defaultValue = "1") Integer pageNum,
                                         @RequestParam(defaultValue = "10") Integer pageSize,
                                         @RequestParam(defaultValue = "") String search) {
        LambdaQueryWrapper<Prediction3> wrapper = Wrappers.<Prediction3>lambdaQuery();
        if (StrUtil.isNotBlank(search)) {
            wrapper.like(Prediction3::getId, search);
        }
        Page<Prediction3> predictionPage = prediction3Mapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
        return Result.success(predictionPage);
    }
}